import scala.collection.mutable.ListBuffer

object Demo12List {
  def main(args: Array[String]): Unit = {
    /**
     * List列表
     * 特点：元素可以重复、有序、不可变的
     */
    // 定义一个List
    val list1: List[Int] = List[Int](1, 1, 6, 7, 9, 2, 3, 4, 5, 6, 7)
    println(list1)

    // 通过下标（index索引）取元素
    println(list1(4))
    //    list1(4) = 99 // List不能修改

    // List中常用的方法
    println(list1.max) // 最大值
    println(list1.min) // 最小值
    println(list1.sum) // 求和
    println(list1.head) // 取第一个元素
    println(list1.tail) // 取除一个元素以外的元素
    println(list1.length) // 长度 同size
    println(list1.size) // 大小 同length
    println(list1.take(3)) // 取前N个元素
    println(list1.distinct) // 返回去重后结果
    println(list1.isEmpty) // 判断是否为空
    println(list1.reverse) // 倒转List

    // List常见的操作
    /**
     * map 和 foreach
     * 区别：有无返回值
     * 都需要接收一个函数f
     * 都会将List中的每个元素传给函数f
     */

    // 有返回值
    val newList1: List[Int] = list1.map(elem => elem * elem)
    println(newList1.mkString(","))
    // 遍历
    list1.foreach(println)

    /**
     * 过滤
     * filter方法：
     * 接收一个函数类型的参数p
     * p: Int => Boolean
     * 函数p的参数类型为Int：因为list1中的每个元素的类型为Int
     * 函数p的返回值类型为Boolean
     * filter会根据函数p最后的返回值进行过滤
     * true：保留数据
     * false：将数据过滤
     */
    // 将奇数过滤出来
    def filterList1(elem: Int): Boolean = {
      var flag: Boolean = false
      if (elem % 2 == 1) {
        flag = true
      }
      flag
    }

    // 使用一般的函数
    val filterList: List[Int] = list1.filter(filterList1)
    println(filterList.mkString(","))

    // 使用匿名函数
    val filterList2: List[Int] = list1.filter(elem => {
      var flag: Boolean = false
      if (elem % 2 == 1) {
        flag = true
      }
      flag
    })
    println(filterList2.mkString(","))
    // 简写
    println(list1.filter(elem => elem % 2 == 1).mkString(","))
    println(list1.filter(_ % 2 == 0).mkString(",")) // 偶数
    println(list1.filter(_ % 2 == 1).mkString(",")) // 奇数

    // groupBy 需要指定一个分组“字段”
    val zs: StuL = StuL("001", "zs", 20, "理科")
    val ls: StuL = StuL("002", "ls", 21, "文科")
    val ww: StuL = StuL("003", "ww", 22, "文科")
    val ll: StuL = StuL("004", "ll", 22, "理科")

    val stuList: List[StuL] = List[StuL](zs, ls, ww, ll)

    stuList.map((stu: StuL) => {})

    // 按班级分组
    //    stuList.groupBy((stu:Stu)=>{stu.clazz})
    /**
     * 得到一个Map
     * Map的Key就是指定的分组“字段” 表示每一个组
     * Map的Value就是经过分组过后属于同一组的元素一同构成的List
     */
    val groupStu: Map[String, List[StuL]] = stuList.groupBy(_.clazz)
    println(groupStu)

    groupStu.map((kv) => {
      val clazz: String = kv._1
      val stus: List[StuL] = kv._2
      (clazz, stus.size)
    }).foreach(println)

    groupStu.map(kv => (kv._1, kv._2.size)).foreach(println)

    /**
     * flatMap: 接收一个函数f
     * 函数f： String => GenTraversableOnce
     * String： 因为List中每一个元素是String类型
     * GenTraversableOnce：所有可以遍历的类型
     * flatMap不仅会将List中的每个元素传给函数f处理
     * 并且会将函数f的返回值进行 扁平化处理（展开）
     */
    val linesList: List[String] = List[String]("hadoop,hive,hbase", "hadoop,hive,hbase", "spark,flink", "python,java,java,java")
    val list: List[Array[String]] = linesList.map(line => {
      val words: Array[String] = line.split(",")
      words
    })

    val wordsList: List[String] = linesList.flatMap(line => {
      val words: Array[String] = line.split(",")
      words
    })
    wordsList.foreach(println)
    println(wordsList.length)
    // 按照每个单词进行分组
    wordsList
      .groupBy(word => word)
      .map(kv => (kv._1, kv._2.size))
      .foreach(println)

    // 排序
    val list2: List[Int] = List[Int](-1, 8, 4, 6, 8, 7, 5, 3, -10, -5 - 6)

    /**
     * sorted 按照自然升序排列
     */
    println(list2.sorted) // 返回一个新的List，并不会对原有的List造成改变

    /**
     * sortWith
     * 类似Java中的CompareTo
     * 给定一个排序规则
     */

    println(list2.sortWith((i, j) => i > j)) // 降序
    println(list2.sortWith((i, j) => i < j)) // 升序
    println(list2.sortWith((i, j) => Math.abs(i) > Math.abs(j))) // 按照绝对值降序

    println(list2) // List默认是不可变的 所以不管做任何操作 List始终同创建时一致

    /**
     * sortBy
     * 可以指定一个排序字段
     */
    println(stuList)
    // 按照年龄排序
    println(stuList.sortBy(_.age)) // 升序排列
    println(stuList.sortWith((stu1, stu2) => {
      stu1.age > stu2.age
    })) // 降序排列

    // 可变的List---> ListBuffer
    val listBF: ListBuffer[Int] = ListBuffer[Int](1, 2, 3, 4, 5, 8, 7, 9)
    println(listBF)

    // 增
    listBF.append(10)
    listBF.append(11)
    listBF.insert(5, 6, 7)
    println(listBF)

    // 删
    listBF.remove(7) // 删除索引为7的元素
    println(listBF)
    listBF.remove(7, 2) // 删除索引为7的元素 两次
    println(listBF)

    // - -= 区别在于是否会改变自身
    val ints: ListBuffer[Int] = listBF - 7
    println(ints)

    listBF -= 7 // 移除值为7的元素
    println(listBF)

    // 改
    listBF(6) = 7
    println(listBF)
    listBF.update(7, 8)
    println(listBF)

    // 查
    println(listBF(5))

  }

}

case class StuL(id: String, name: String, age: Int, clazz: String)

